home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d12
/
todir1.arc
/
TODIR.ASM
< prev
next >
Wrap
Assembly Source File
|
1990-08-14
|
29KB
|
1,043 lines
title TODIR - Change dir through alias
subttl Prologue
page 60, 132
comment {
******************************************************************************
File TODIR.ASM
Author:
Aaron Brenner
GEnie mail address A.BRENNER
BIX user id albrenner
This program is hereby released to the public domain.
Purpose:
Provide a shorthand for CHDIR. TODIR will read the file TODIR.PTH in
either the current directory, on the PATH, or in the directory speci-
fied by the TODIRPTH environment variable. TODIR.PTH must be an ASCII
file containing shorthand/path pairs, one per line, blank separated.
Alias are limited to 12 characters in length, and may contain any
printable characters.
Syntax:
C>TODIR
Displays a usage message.
C>TODIR
Displays all alias/path pairs.
C>TODIR <path alias>
Changes the current directory (and current drive, if necessary) to the
path corresponding to <path alias>.
Errorlevel set:
0 Path set successfully.
1 Unable to locate TODIR.PTH.
2 Unable to locate alias in TODIR.PTH.
3 No path associated with alias.
4 Unable to change drive/directory to path.
5 No command argument present.
6 Not enough memory
Revision history:
1.00 07/15/90 ALB Created.
******************************************************************************
endcomment {
subttl Macros
page
save macro p1,p2,p3,p4,p5,p6,p7,p8,p9
irp y,<p1,p2,p3,p4,p5,p6,p7,p8,p9>
ifnb <y>
push y
endif
endm
restore macro
irp z,<p9,p8,p7,p6,p5,p4,p3,p2,p1>
ifnb <z>
pop z
endif
endm
endm
endm
subttl Program stack and data
page
todir_stack segment stack
dw 128 dup(0)
todir_stack ends
todir_data segment
$buf_size equ 4096
our_env_seg dw 0 ; Pointer to our environment segment
our_PSP dw 0 ; Our PSP segment
buffer_posn dw $buf_size ; Current position in the buffer
buffer_seg dw 0 ; Segment of the file buffer
buffer_count dw 0 ; Count of characters in the buffer
saved_char dw -1 ; An ungotten character
line_buf db 128 dup (0) ; Buffer for a line
;*****************************************************************************
;
; Error messages
;
; Note that the routine that does the output will interpret the following
; control characters:
; ^A output the alias entered on the command line
; ^B output the path associated with the alias
;
;*****************************************************************************
usage_msg db 'TODIR v1.00 - Public Domain Software', 13, 10, 13, 10
db 'Usage: TODIR <path alias>', 13, 10
db ' or TODIR ?', 13, 10
db ' or TODIR <path alias> ?', 13, 10, 13, 10
db 'Change drive/directory to the path corresponding to'
db ' <path alias> as set', 13, 10
db 'in TODIR.PTH.', 13, 10
db 'An argument of ? will display all alias/path pairs in'
db ' TODIR.PTH.', 13, 10
db 'A <path alias> followed by ? will display the path'
db ' associated with that alias.', 13, 10, '$'
all_aliases db 'All aliases in ', 3, ':', 13, 10, 0
no_alias_path db 'No path associated with "', 1, '".', 13, 10, 0
no_alias_fnd db 'Alias "', 1, '" not found.', 13, 10, 0
bad_path db 'Unable to change to "', 2, '".', 13, 10, 0
no_pth_file db 'Unable to locate alias definition file.', 13, 10, '$'
no_memory db 'Not enough free memory', 13, 10, '$'
crlf_string db 13, 10
command_tail db 127 dup (0) ; Copy of our command tail
alias_name db 14 dup (0) ; The alias they entered
alias_path db 80 dup (0) ; The path associated with it
possible_alias db 14 dup (0) ; A possible one from the file
path_file_name db 80 dup (0) ; Where we found TODIR.PTH
path_file_hnd dw -1 ; Handle for it
path_name_base db 'TODIR.PTH',0 ; Base name of path file
$name_base_len = $ - path_name_base
;
; Environment variables to look for
;
env_path db 'PATH='
$env_path_len = $ - env_path
env_todir db 'TODIRPTH='
$env_todir_len = $ - env_todir
env_buffer db 256 dup (0) ; Buffer to hold the env contents
todir_data ends
subttl Program code
page
todir_code segment
assume cs:todir_code, ds:nothing, es:nothing, ss:todir_stack
start proc
call initialize ; Set everything up
call change_path ; Change to where they want
mov ax,4c00h ; Exit to DOS with ERRORLEVEL 0
int 21h ;
start endp
subttl Program initialization
page
;*****************************************************************************
;
; Program initialization
;
;*****************************************************************************
initialize proc near
mov ax,todir_data ; Set up our data segment
mov es,ax ;
assume es:todir_data
mov es:our_PSP,ds ; Save our PSP segment
mov ax,ds:[2ch] ; Get our environment segment
mov es:our_env_seg,ax ; Save it
mov di,offset command_tail ; Point to our buffer for the cmd tail
mov si,81h ; Point to our command tail
mov cl,ds:[80h] ; Get the length of the command tail
sub ch,ch ; as a word
cld ; Make sure of direction
rep movsb ; Copy the command tail
sub al,al ; Null-terminate it
stosb ;
push es ; Set our data segment now
pop ds ;
assume ds:todir_data
mov si,offset command_tail ; Point to our copy of the cmd tail
mov di,offset alias_name ; Point to alias name buffer
mov cx,12 ; Max to copy
call copy_string ; Copy it
cmp byte ptr alias_name[0],0; Did they enter one?
jne init_l2 ; Yep - check for "?"
;
; No command line arg. Just display the usage message and exit 5.
;
mov dx,offset usage_msg ; Point to the usage message
mov ah,9 ; Display it to console
int 21h ; Display the usage message
mov ax,4c05h ; Exit with ERRORLEVEL of 5
int 21h ;
init_l2:
mov bx,offset program_end + 15; Figure out where we end
mov cl,4 ;
shr bx,cl ;
mov ax,cs ;
add bx,ax ;
sub bx,our_PSP ; Figure out our size
push es ; Save this for a sec
mov es,our_PSP ; for the SETBLOCK call
mov ah,4ah ; Set our allocation
int 21h ;
pop es ;
mov ah,48h ; Now, allocate a file buffer
mov bx,$buf_size shr 4 ; Number of paragraphs for the buffer
int 21h ;
jnc init_l3 ; We got it - continue
mov dx,offset no_memory ; Report there ain't enough RAM
mov ah,9 ;
int 21h ;
mov ax,4c06h ; Exit with appropriate ERRORLEVEL
int 21h ;
init_l3:
mov buffer_seg,ax ; Save the returned segment
call locate_file ; Get the file
cmp word ptr alias_name[0],('?' * 256) + 1; Was it just "?"?
jne init_l4 ; No - see if more args
;
; The first command line arg was a "?". We just want to display the entire
; list of alias/path pairs.
;
call display_file ; Display the .PTH file
mov ax,4c00h ; Pretend we did the change
int 21h ;
;
init_l4:
call skip_spaces ; Skip any more whitespace
lodsb ; Get the next byte
or al,al ; End of the command line?
je init_exit ; Yep - finish up here
cmp al,'?' ; Are they querying?
jne init_exit ; No - just finish up
call match_alias ; Match the alias they entered
call display_pair ; Display the alias/path pair
mov ax,4c00h ; Pretend we did the change
int 21h ;
;
init_exit:
call match_alias ; Find a match for the alias
ret ; Return to Main
initialize endp
;*****************************************************************************
;
; Attempt to change the drive/path to that in alias_path.
;
;*****************************************************************************
change_path proc near
assume ds:todir_data, es:todir_data
cmp byte ptr alias_path[0],0; Is there a path there?
jne chgp_l1 ; Yes - try to change to it
mov si,offset no_alias_path ; Point to error message
call display_message ; Spit it out
mov ax,4c03h ; Exit with ERRORLEVEL 3
int 21h ;
;
chgp_l1:
mov dx,offset alias_path[1] ; Point to the path to switch to
mov ah,3bh ; DOS fn to change current dir
int 21h ; Try to do it
jnc chgp_l2 ; It flew - continue
mov si,offset bad_path ; Point to error message
call display_message ; Show it
mov ax,4c04h ; Exit with appropriate ERRORLEVEL
int 21h ;
;
chgp_l2:
mov ax,word ptr alias_path[1]; Get the first 2 bytes of the string
cmp ah,':' ; Is there a drive present?
jne chgp_exit ; Nope - we're done
sub al,'A' ; Make it a disk number
mov dl,al ; Put it where DOS wants
mov ah,0eh ; Fn to select drive
int 21h ;
chgp_exit:
ret ; Return to Main
change_path endp
subttl Various utility routines
page
;*****************************************************************************
;
; U t i l i t y R o u t i n e s
;
;*****************************************************************************
;*****************************************************************************
;
; Locate the file TODIR.PTH. The search order is:
; 1. In the path specified by the TODIRPTH environment variable. If this
; specifies a directory, the file name is assumed to be TODIR.PTH.
; 2. In a directory specified by the PATH environment variable.
; 3. In the current directory.
;
; Input:
; None.
;
; Output:
; path_file_name is filled in with the file spec, and the handle for
; the file is stored in path_file_handle
;
; Registers:
; All preserved.
;
;*****************************************************************************
locate_file proc near
assume ds:todir_data, es:todir_data
save ax, bx, cx, dx, si, di
mov si,offset env_todir ; Point to the "TODIRPTH" var name
mov cx,$env_todir_len ; Get the length of it
call getenv ; Try to get it
cmp byte ptr env_buffer[0],0; Is there a path there?
je lctf_on_path ; Nope - look along the path
mov si,offset env_buffer ; Copy it into our path
mov di,offset path_file_name;
mov cx,78 ;
call copy_string ;
cmp byte ptr [di - 1],'\' ; Is there a path sep?
je lctf_l1 ; Yep - just tack on the file name
cmp byte ptr [di - 1],'/' ; Check for other path sep
je lctf_l1 ; Yep - tack on the file name
mov dx,offset path_file_name[1];
mov ax,4300h ; See if it's a file or a dir
int 21h ;
jc lctf_on_path ; If unable, look along the path
test cx,10h ; Is this a directory?
jz lctf_l2 ; Nope - use that file name
mov al,'\' ; Put in a path separator
stosb ;
inc path_file_name ; Account for it
lctf_l1:
mov si,offset path_name_base; Point to the file name
mov cx,$name_base_len ; Size of it
rep movsb ; Copy to the path (terminates it, too)
add path_file_name,$name_base_len - 1; Add to string length
lctf_l2:
mov dx,offset path_file_name[1]; Get ready to open it
mov ax,3d00h ; Open for read-only
int 21h ; Try to open that puppy
jnc lctf_done ; If we did, save the handle & exit
lctf_on_path:
mov si,offset env_path ; Point to "PATH="
mov cx,$env_path_len ; Get the length of it
call getenv ; Get the value for it
cmp env_buffer[0],0 ; Is there a PATH defined?
je lctf_curr_dir ; Nope - try current directory
;
; To make things a little easier to deal with, step through the PATH string,
; replacing ";" with " ".
;
mov si,offset env_buffer ; Point to the PATH string
mov di,si ; Twice
lctf_l3:
lodsb ; Get a character
cmp al,';' ; Is it one we need to change?
jne lctf_l4 ; No - store it
mov al,' ' ; Replace it with a blank
lctf_l4:
stosb ; Stuff it back in
or al,al ; Hit the end yet?
jnz lctf_l3 ; Nope - check the whole thing
mov si,offset env_buffer ; Start back at the beginning
lctf_l5:
mov di,offset path_file_name; Point to the final path name
mov cx,65 ; Biggest path allowed by DOS
call copy_string ; Copy it in
cmp path_file_name[0],0 ; Is there anything there?
je lctf_curr_dir ; No - look in the current directory
cmp byte ptr [di - 1],'\' ; Is there a path sep?
je lctf_l6 ; Yes - just add the file name
cmp byte ptr [di - 1],'/' ; Other path sep?
je lctf_l6 ; Yep - continue
mov al,'\' ; Add a path separator
stosb ;
inc path_file_name ; Account for it in the length
lctf_l6:
push si ; Save where we were
mov si,offset path_name_base; Point to the actual file name
mov cx,$name_base_len ; Size of it
rep movsb ; Copy it into the final file spec
pop si ;
add path_file_name[0],$name_base_len - 1; Account for it
mov dx,offset path_file_name[1]; Try to open that baby
mov ax,3d00h ;
int 21h ;
jnc lctf_done ; If it went, save the handle & exit
jmp short lctf_l5 ; Not there - try next path
lctf_curr_dir:
;
; The file isn't on the path and it isn't in the TODIRPTH path. Try the
; current directory. If it isn't there, report an error.
;
mov dx,offset path_name_base; Point to base file name
mov ax,3d00h ; Try to open it
int 21h ;
jnc lctf_done ; No error - save the handle and exit
mov dx,offset no_pth_file ; Let 'em know we couldn't find it
mov ah,9 ;
int 21h ;
mov ax,4c01h ; Exit w/ERRORLEVEL of 1
int 21h ;
;
lctf_done:
mov path_file_hnd,ax ; Save the handle
restore
ret ; Return to caller
locate_file endp
;*****************************************************************************
;
; Retrieve the contents of an environment variable.
;
; Input:
; DS:SI pointer to the name (including the "=") of the var
; CX length of the name (including the "=")
;
; Output:
; env_buffer will be filled with the contents of the variable. If the
; first byte of env_buffer is 0, then the variable wasn't found. Up to
; 255 characters will be copied.
;
; Registers:
; All preserved.
;
;*****************************************************************************
getenv proc near
assume ds:todir_data, es:todir_data
save ax, bx, cx, dx, di, ds
mov es,our_env_seg ; Get our environment segment
assume es:nothing
sub ax,ax ; We'll be scanning for a 0 byte
sub di,di ; Start at the beginning of it
mov bx,si ; Save the pointer to the name
mov dx,cx ; Save its length
gtnv_l1:
repe cmpsb ; See if we've found it
je gtnv_l2 ; Yep - copy the contents
mov cx,-1 ; Look forever for the end of this one
repne scasb ; Find the end of this var
mov si,bx ; Restore the pointer & length
mov cx,dx ;
cmp byte ptr es:[di],0 ; End of the environment?
jne gtnv_l1 ; No - keep looking
gtnv_l2:
mov si,di ; Get ready to copy from the environment
push ds ; Swap segments
push es ;
pop ds ;
pop es ;
assume ds:nothing, es:todir_data
mov di,offset env_buffer ; Point to the destination
mov cx,255 ; Max to copy
gtnv_l3:
lodsb ; Copy a byte
stosb ;
or al,al ; Did we just copy the ender?
loopnz gtnv_l3 ; Loop if not
restore
assume ds:todir_data
ret ; Return to caller
getenv endp
;*****************************************************************************
;
; Display an alias/path pair
;
; Input:
; possible_alias set to the alias to display
; alias_path set to the corresponding path
;
; Output:
; Both are displayed.
;
; Registers:
; All preserved.
;
;*****************************************************************************
display_pair proc near
save ax, bx, cx, dx, si
mov si,offset possible_alias; Display the alias name first
mov al,[si] ; Get the length
cbw ; as a word
call display_string ; Display the alias
mov cx,16 ; Use field width of 16
sub cx,ax ; Figure out how many blanks to output
mov dl,' ' ;
dspp_l1:
mov ah,6 ; Output a space
int 21h ;
loop dspp_l1 ; Loop to fill out field
mov si,offset alias_path ; Now, display the associated path
call display_string ;
mov dx,offset crlf_string ; End this line
mov cx,2 ;
mov bx,1 ;
mov ah,40h ;
int 21h ;
restore
ret ; Return to caller
display_pair endp
;*****************************************************************************
;
; Display the entire alias file
;
; Input:
; path_file_hnd handle to read from
;
; Output:
; The file is displayed as a series of alias/path pairs.
;
; Registers:
; All preserved.
;
;*****************************************************************************
display_file proc near
save si
mov si,offset all_aliases ; Display the name of the file
call display_message ;
dspf_l1:
call get_pair ; Get a pair from the file
jc dspf_exit ; If EOF, we're done
call display_pair ; Display that pair
jmp short dspf_l1 ; Loop back 'til EOF
dspf_exit:
restore
ret ; Return to caller
display_file endp
;*****************************************************************************
;
; Read an alias/path pair from the file
;
; Input:
; None.
;
; Output:
; CF = 1 EOF has been reached (^Z is recognized as EOF)
; CF = 0:
; possible_alias the alias read from the file
; alias_path the corresponding path
;
; Registers:
; All preserved
;
;*****************************************************************************
get_pair proc near
save cx, si, di
getp_l1:
call get_line ; Get a line from the file
jc getp_exit ; Exit if EOF
cmp line_buf[0],0 ; Empty line?
je getp_l1 ; Yep - ignore it
mov si,offset line_buf ; Point to the line buffer
mov di,offset possible_alias; And to the name buffer
mov cx,12 ; Max to copy
call copy_string ; Copy the alias name
cmp possible_alias[0],0 ; Empty line?
je getp_l1 ; Yep - ignore it
mov di,offset alias_path ; Point to the path buffer
mov cx,65 ; Max to copy
call copy_string ; Copy to the aliased path
clc ; Make sure we return success
getp_exit:
restore
ret ; Return to caller
get_pair endp
;*****************************************************************************
;
; Get a line of text from the path file
;
; Input:
; None.
;
; Output:
; CF = 1 EOF has been reached.
; CF = 0:
; line_buf is set to the next line from the file. All alphas are
; folded to upper case.
;
; Registers:
; All preserved.
;
;*****************************************************************************
get_line proc near
assume ds:todir_data, es:todir_data
save ax, cx, di
mov di,offset line_buf ; Point to our line buffer
mov cx,127 ; Max to store
getl_l1:
call get_char ; Get a character from the file
jz getl_EOF ; Exit if EOF
cmp al,13 ; Is it a CR?
je getl_l2 ; Yep - check for LF following
cmp al,10 ; Is it a LF?
je getl_l3 ; Yep - check for CR following
jcxz getl_l1 ; Ignore it if the buffer's full
call casetize ; Make it upper case
stosb ; Stuff it in
dec cx ; Knock it off the count
jmp short getl_l1 ; Loop back for more
getl_l2:
call get_char ; Get the NEXT character
jz getl_eof ; Stop if EOF
cmp al,10 ; Is it the LF following a CR?
je getl_exit ; Yep - we're done with this line
mov ah,1 ;
mov saved_char,ax ; Save it for next time
jmp short getl_exit1 ; Exit now
getl_l3:
call get_char ; Get the NEXT character
jz getl_eof ; Stop if EOF
cmp al,13 ; Is it the CR following a LF?
je getl_exit ; Yep - we're done with this line
mov ah,1 ;
mov saved_char,ax ; Save it for next time
jmp short getl_exit1 ; Exit now
getl_EOF:
;
; We get here when get_char reports we've reached EOF. We only want to return
; EOF when the line's empty.
;
cmp di,offset line_buf[1] ; Are we at the beginning of the buf?
jmp short getl_exit ; If we are, CF will be 1
getl_exit1:
clc ; Make sure we don't report EOF
getl_exit:
mov byte ptr [di],0 ; Terminate the line buffer
restore
ret ; Return to caller
get_line endp
;*****************************************************************************
;
; Attempt to match the alias from the command line with one from the file.
;
; Input:
; alias_name set to the alias to look for
;
; Output:
; alias_path set to the corresponding path
;
; Registers:
; All preserved.
;
;*****************************************************************************
match_alias proc near
save cx, si, di
mov ch,0 ; Make sure high byte is clear
mtch_l1:
call get_pair ; Get an alias/path pair
jc mtch_err ; Oops - if EOF, no matches
mov cl,alias_name[0] ; Get length of our alias
inc cl ; Allow for length byte
mov si,offset alias_name ; Point to the one they entered
mov di,offset possible_alias; Point to the one from the file
repe cmpsb ; See if they match
jnz mtch_l1 ; Nope - keep trying
restore
ret ; Return to caller
;
mtch_err:
;
; We get here if we hit EOF - that means that there is no possible match for
; the given alias.
;
mov si,offset no_alias_fnd ; Let 'em know it ain't there
call display_message ;
mov ax,4c02h ; Exit with appropriate ERRORLEVEL
int 21h ;
match_alias endp
;*****************************************************************************
;
; Get the next character from the file.
;
; Input:
; buffer_seg segment of file data buffer
; buffer_posn current position the buffer
; buffer_count number of characters in the buffer
;
; Output:
; ZF = 1 EOF has been reached
; ZF = 0:
; AL next character.
;
; Registers:
; All but AX preserved.
;
;*****************************************************************************
get_char proc near
assume ds:todir_data, es:todir_data
save si, es
sub ax,ax ; See if there was a saved character
dec ax ;
xchg ax,saved_char ;
cmp ax,-1 ;
je getc_l1 ; Nope - read the next one in
or ax,ax ; Make sure and clear ZF
jmp short getc_exit ; Exit now
getc_l1:
cmp buffer_count,0 ; Is the buffer empty?
jne getc_l2 ; Nope - read the next byte from it
call fill_buffer ;
jz getc_exit ; EOF - return it
getc_l2:
les si,dword ptr buffer_posn; Point at the next available byte
assume es:nothing
lods byte ptr es:[si] ; Get it from the buffer
cmp al,1ah ; Is it the fake EOF?
je getc_exit ; Yep - exit with ZF set
dec buffer_count ; Knock it off the count
mov buffer_posn,si ; Save updated buffer position
or si,si ; Clear ZF for return
getc_exit:
restore
assume es:todir_data
ret ; Return to caller
get_char endp
;*****************************************************************************
;
; Fill the buffer from the file.
;
; Input:
; path_file_hnd handle to read from
;
; Output:
; ZF = 1 EOF has been reached
; ZF = 0:
; buffer_posn set to beginning of buffer
; buffer_count set to the number of bytes actually read
;
; Registers:
; All preserved.
;
;*****************************************************************************
fill_buffer proc near
assume ds:todir_data, es:todir_data
save ax, bx, cx, dx
mov bx,path_file_hnd ; Get the handle
mov cx,$buf_size ; Number of bytes to try to read
sub dx,dx ; Start at 0 in the buffer
push ds ; Save our seg for a sec
mov ds,buffer_seg ; Get the segment for the buffer
mov ah,3fh ; DOS fn to read
int 21h ; Try to read from the file
pop ds ; Get our segment back
jnc filb_l1 ; If no error, reset pointer & count
sub ax,ax ; Act like we hit EOF
filb_l1:
mov buffer_count,ax ; Save how many we read
mov buffer_posn,0 ; Reset to start of buffer
or ax,ax ; If we hit EOF, set ZF
filb_exit:
restore
ret ; Return to caller
fill_buffer endp
;*****************************************************************************
;
; Skip spaces in a string.
;
; Input:
; DS:SI pointer to string
;
; Output:
; DS:SI pointer to first non-blank
;
; Registers:
; All but SI preserved.
;
;*****************************************************************************
skip_spaces proc near
save ax
sksp_l1:
lodsb ; Get a character
cmp al,' ' ; Is it a space?
je sksp_l1 ; Yep - skip it
cmp al,9 ; Is it a tab?
je sksp_l1 ; Yep - skip it
dec si ; Point back to it
restore
ret ; Return to caller
skip_spaces endp
;*****************************************************************************
;
; Copy a string, making it upper case.
;
; Input:
; DS:SI pointer to source buffer. May have leading whitespace,
; and is assumed to be nul-terminated.
; ES:DI pointer to dest buffer.
; CX maximum characters to copy
;
; Output:
; First byte of buffer at DI will be set to the length copied, and all
; alphas are folded to upper case. SI will point to the character just
; *after* the last character that was copied, and DI will point to a
; nul byte at the end of the string.
;
; Registers:
; All but SI and DI preserved.
;
;*****************************************************************************
copy_string proc near
assume ds:todir_data, es:todir_data
save ax, bx, cx
mov byte ptr es:[di],0 ; Clear the dest length
call skip_spaces ; Skip any whitespace
mov bx,di ; Point to the length byte
inc di ; Point to the first available byte
cpys_l1:
lodsb ; Get a byte
or al,al ; End of it?
je cpys_exit ; Yep - exit now
cmp al,' ' ; Whitespace?
je cpys_exit ; Yep - exit
cmp al,9 ; Whitespace?
je cpys_exit ; Yep - exit
jcxz cpys_l1 ; If the buffer's full, ignore it
call casetize ; Make it upper case
stosb ; Store it
inc byte ptr [bx] ; Count it
dec cx ;
jmp short cpys_l1 ; Do the next one
cpys_exit:
sub al,al ; Make sure it's also nul-terminated
stosb ;
dec si ; Point 'em back to the stopping points
dec di ;
restore
ret ; Return to caller
copy_string endp
;*****************************************************************************
;
; Fold a character to upper case.
;
; Input:
; AL character to convert
;
; Output:
; AL converted character
;
; Registers:
; All but AL preserved.
;
;*****************************************************************************
casetize proc near
cmp al,'a' ; Is it lower case?
jb cstz_exit ; Nope - exit
cmp al,'z' ; Are you sure?
ja cstz_exit ; Yep - never mind
xor al,20h ; Make it upper case
cstz_exit:
ret ; Return to caller
casetize endp
;*****************************************************************************
;
; Display a message, allowing for expansion of special control characters.
;
; Input:
; DS:SI pointer to message to display.
;
; Output:
; The message is displayed on the console.
; The following characters in the message will be treated specially:
; ^A (01h) causes the alias name to be displayed
; ^B (02h) causes the associated path to be displayed
; ^C (03h) causes the alias file name to be displayed
;
; Registers:
; All preserved.
;
;*****************************************************************************
display_message proc near
assume ds:todir_data, es:todir_data
save ax, dx, si
dspm_l1:
lodsb ; Get a byte
or al,al ; Is it the end?
jz dspm_exit ; Yep - we're done
cmp al,1 ; Need to display the alias?
jne dspm_l2 ; Nope - check for the path
push si ; Save where we are
mov si,offset alias_name ; Point to the alias name
call display_string ; Display the alias
pop si ; Get our position back
jmp short dspm_l1 ; Loop back
dspm_l2:
cmp al,2 ; Need to display the path?
jne dspm_l3 ; No - check for alias file name
push si ; Save where we are
mov si,offset alias_path ; Point to the path
call display_string ; Display the path
pop si ; Get our position back
jmp short dspm_l1 ; Loop back
dspm_l3:
cmp al,3 ; Need to display the alias file path?
jne dspm_l4 ; No - display this character
push si ; Save where we are
mov si,offset path_file_name; Point to the file name
call display_string ; Display it
pop si ; Get our position back
jmp short dspm_l1
dspm_l4:
mov dl,al ; Put it where DOS wants
mov ah,6 ; Direct I/O function
int 21h ; Display the character
jmp short dspm_l1 ; Loop back
dspm_exit:
restore
ret ; Return to caller
display_message endp
;*****************************************************************************
;
; Display a length-prefixed string.
;
; Input:
; DS:SI pointer to the string to display
;
; Output:
; The string is output to stdout.
;
; Registers:
; All preserved.
;
;*****************************************************************************
display_string proc near
assume ds:todir_data, es:todir_data
save ax, bx, cx, dx, si
mov ah,40h ; Write the string
mov bx,1 ; to stdout
mov cl,[si] ; Get the length byte
mov ch,0 ; Make that a word
mov dx,si ; Get pointer to buffer
inc dx ; Skip the length byte
int 21h ; Display the string
restore
ret ; Return to caller
display_string endp
program_end label byte
todir_code ends
end start